package exquery

import exquery.valuebeans.genericsearch.OrderByClauseVO
import exquery.valuebeans.genericsearch.WhereClauseVO
import org.apache.log4j.Logger
import org.codehaus.groovy.grails.commons.ConfigurationHolder

class GenericSearchController {

    Logger gLogger = Logger.getLogger(GenericSearchController.class)

    def genericSearchService

    // Export service provided by Export plugin
    def exportService
  
   /**
    * Main Page for Generic Search Application  
    */
    def index = {

      def SelectList = genericSearchService.getAllSelectOptions()

      def SearchCriteria = SelectList
      String SearchCriteriaString = "<option value='-1'> ---Select--- </option>"

      SearchCriteria?.each{criteria ->
        SearchCriteriaString += "<option value='${criteria.groupkey}.${criteria.db_object}' title='${criteria.description != null && criteria.description.toString().trim().length() >0 ? criteria.description : criteria.title }'> ${criteria.title} </option>"
      }

      def OrderMap = SelectList
      String OrderMapString = "<option value='-1'> ---Select--- </option>"

      OrderMap?.each{order ->
        OrderMapString += "<option value='${order.groupkey}.${order.db_object}' title='${order.description != null && order.description.toString().trim().length() >0 ? order.description : order.title }'> ${order.title} </option>"
      }


      gLogger.info ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
      gLogger.info params
      gLogger.info ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>"

      return ["SelectList":SelectList,"SearchCriteria":SearchCriteria,"OrderMap":OrderMap,"SearchCriteriaString":SearchCriteriaString,"OrderMapString":OrderMapString,"paramSelectList" : params.Select,"countWhereClause":params.countWhereClause,"countOrderByClause":params.countOrderByClause,"params":params]
    }

    /**
     * Process Generic Search Request 
     */
    def process = {

      gLogger.info "Comming into action-> process of GenericSearchController"

      gLogger.info params

      def isExport = params.isExport

      if( isExport!=null && isExport ){
        doExport(params)
      }else{
        gLogger.info "Select : ${params.Select}"
        gLogger.info "countWhereClause : ${params.countWhereClause}"
        gLogger.info "countOrderByClause : ${params.countOrderByClause}"

        def valid = validatePage(params)

        if(valid!=null){
          //render "<div class='errors'>${valid}</div>"
          flash.message = valid
          redirect(action: "index", "params": params)
        }else{
          return doProcess(params)
        }
      }
    }

    // Export Result
    void doExport(def params){

      if(params?.format && params.format != "html"){
        response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
        response.setHeader("Content-disposition", "attachment; filename=GenericSearchResult.${params.extension}")
        def resultData = null
        if(session.getAttribute("resultData")!=null)
        {
          resultData = session.getAttribute("resultData")
        }
        exportService.export(params.format, response.outputStream, resultData.resultList, resultData.fieldList, resultData.labelMap, resultData.formatters, resultData.parameters)
      }
      
    }

   /**
    * function for actual process logic 
    * @param params
    * @return
    */
    private def doProcess(def params) {

      gLogger.info "Comming into method doProcess of GenericSearchController"

      gLogger.info params

      gLogger.info "Select : ${params.Select}"
      gLogger.info "countWhereClause : ${params.countWhereClause}"
      gLogger.info "countOrderByClause : ${params.countOrderByClause}"

      //prepare select list
      def selectList = []

      if(params.Select!=null){
         params.Select.each {String selectColumn->
            gLogger.info "${selectColumn}"
            selectList.add(selectColumn)
         }
      }

      int countWhereClause = Integer.parseInt(params.countWhereClause.toString())
      int countOrderByClause = Integer.parseInt(params.countOrderByClause.toString())

      //Collect Where Clause : Start
      WhereClauseVO[] whereClauseVOList = new WhereClauseVO[countWhereClause]
      for ( index in 1..countWhereClause) {
        whereClauseVOList[index-1] = new WhereClauseVO();

        whereClauseVOList[index-1].setOption(params."cmbOption${index}")
        whereClauseVOList[index-1].setCriteria(params."cmbCriteria${index}")
        whereClauseVOList[index-1].setOperation(params."cmbOperation${index}")
        whereClauseVOList[index-1].setSearchData(params."txtSearchData${index}")

        gLogger.info "=============="
        gLogger.info "whereClauseVOList[${index}] : ${whereClauseVOList[index-1].show()} "

        if(selectList!=null && !selectList.contains(params."cmbCriteria${index}".toString())){
            selectList.add(params."cmbCriteria${index}".toString())
        }
      }
      //Collect Where Clause : End

      //Collect OrderBy Clause : Start
      OrderByClauseVO[] orderByClauseVOList = new OrderByClauseVO[countOrderByClause]
      def orderByMap = [:]
      for ( index in 1..countOrderByClause) {
        orderByClauseVOList[index-1] = new OrderByClauseVO();

        orderByClauseVOList[index-1].setOrderBy(params."cmbOrderByOption${index}")
        orderByClauseVOList[index-1].setOrderType(params."cmbType${index}")

        def oredrBy = params."cmbOrderByOption${index}"
        oredrBy = oredrBy.toString().trim().toUpperCase().replaceAll("[.]","_") 
        orderByMap.putAt oredrBy,params."cmbType${index}"

        gLogger.info "=============="
        gLogger.info "orderByClauseVOList[${index}] : ${orderByClauseVOList[index-1].show()} "

        if(selectList!=null && !selectList.contains(params."cmbOrderByOption${index}".toString())){
            selectList.add(params."cmbOrderByOption${index}".toString())
        }
      }
      //Collect OrderBy Clause : End

      gLogger.info "orderByMap :: ${orderByMap}"
      gLogger.info "selectList :: ${selectList}"

      def resultList = genericSearchService.processQuery(selectList,whereClauseVOList,orderByClauseVOList);

      def resultData = genericSearchService.prepareExperimentsResult(resultList,selectList)

      def whereClause = genericSearchService.getWhereClauseString(whereClauseVOList)

      gLogger.info "Comming whereClause here... ${whereClause.class}"

      if(whereClause!=null && whereClause instanceof String){
        gLogger.info "Comming here..."
        whereClause = whereClause.toString().replaceAll("['][']","'")
      }


      if( resultData != null && resultData.size() > 0 ){
        session.setAttribute "resultData",resultData
      }

      gLogger.info "Out from method doProcess of GenericSearchController"
      return [result: resultData,params:params,whereClause:whereClause,orderByMap:orderByMap]
    }

  /**
   * validate generic search inputs
   * @param params
   * @return
   */
  private def validatePage(def params){

     def selectList = params.Select

     if( selectList == null || selectList.size() == 0 ){
       return "Please select at least one value in Select Block"
     }

     if(params.countWhereClause!=null){
       int countWhereClause = Integer.parseInt(params.countWhereClause.toString())
       if( countWhereClause == 0 ){
         return "Please fill at least one row in where Block"
       }else
       if( countWhereClause > 0 ){
         for ( index in 1..countWhereClause) {
            String Criteria = params."cmbCriteria${index}"
            String Operation = params."cmbOperation${index}"
            if( Criteria.equals("-1")){
              return "Select Criteria in row number : ${index} of Where Block"
            }else
            if( Operation.equals("-1")){
              return "Select Operation in row number : ${index} of Where Block"
            }
         }
       }
     }else{
       return "Please fill at least one row in where Block"
     }

     if(params.countOrderByClause!=null){
       int countOrderByClause = Integer.parseInt(params.countOrderByClause.toString())
       if( countOrderByClause == 0 ){
         return "Please fill at least one row in OrderBy Block"
       }else
       if( countOrderByClause > 0 ){
         for ( index in 1..countOrderByClause) {
            String OrderByOption = params."cmbOrderByOption${index}"
            if( OrderByOption.equals("-1")){
              return "Select Options in row number : ${index} of OrderBy Block"
            }
         }
       }
     }else{
       return "Please fill at least one row in OrderBy Block"
     }
    
     return null
  }
  
}
